package com.geek.bucks;

import com.geek.bucks.entity.Coffee;
import com.geek.bucks.entity.CoffeeOrder;
import com.geek.bucks.entity.OrderState;
import com.geek.bucks.repository.CoffeeOrderRepository;
import com.geek.bucks.repository.CoffeeRepository;
import lombok.extern.slf4j.Slf4j;
import org.joda.money.BigMoney;
import org.joda.money.CurrencyUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.transaction.Transactional;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@SpringBootApplication
@Slf4j
@EnableJpaRepositories
@EnableTransactionManagement
public class CoffeeBucksApplication implements ApplicationRunner {

    public static void main(String[] args) {
        SpringApplication.run(CoffeeBucksApplication.class, args);
    }

    @Autowired
    private CoffeeRepository coffeeRepository;

    @Autowired
    private CoffeeOrderRepository coffeeOrderRepository;

    @Override
    @Transactional
    public void run(ApplicationArguments args) {
//        initOrders();
//
//        findOrders();
    }

    private void findOrders() {
        coffeeRepository.findAll(Sort.by(Sort.Direction.DESC, "id")).forEach(coffee -> log.info("Loading {}", coffee));

        List<CoffeeOrder> top3ByOrderByUpdateTimeDescIdAsc = coffeeOrderRepository.findTop3ByOrderByUpdateTimeDescIdAsc();
        log.info("findTop3ByOrderByUpdateTimeDescIdAsc: {}", getJoinedOrderId(top3ByOrderByUpdateTimeDescIdAsc));

        List<CoffeeOrder> coffeeOrders = coffeeOrderRepository.findByCustomerOrderById("Li Lei");
        log.info("findByCustomerOrderById: {}", getJoinedOrderId(coffeeOrders));
        coffeeOrders.forEach(coffeeOrder -> {
            log.info("Oder: {}", coffeeOrder.getId());
            coffeeOrder.getItems().forEach(coffee -> log.info("  Item {}", coffee));
        });

        List<CoffeeOrder> lattes = coffeeOrderRepository.findByItems_Name("latte");
        log.info("findByItems_Name: {}", getJoinedOrderId(lattes));

    }

    private String getJoinedOrderId(List<CoffeeOrder> top3ByOrderByUpdateTimeDescIdAsc) {
        return top3ByOrderByUpdateTimeDescIdAsc.stream().map(coffeeOrder -> coffeeOrder.getId().toString()).collect(Collectors.joining(","));
    }

    private void initOrders() {
        Coffee espresso = Coffee.builder().name("espresso").price(BigMoney.of(CurrencyUnit.of("CNY"), 20.00)).build();
        Coffee latte = Coffee.builder().name("latte").price(BigMoney.of(CurrencyUnit.of("CNY"), 30.00)).build();

        coffeeRepository.save(espresso);
        log.info("Coffee: {}", espresso);

        coffeeRepository.save(latte);
        log.info("Coffee: {}", latte);

        CoffeeOrder order1 = CoffeeOrder.builder().customer("Li Lei").items(Collections.singletonList(espresso)).state(OrderState.INIT).build();
        CoffeeOrder order2 = CoffeeOrder.builder().customer("Li Lei").items(Arrays.asList(espresso, latte)).state(OrderState.PAID).build();

        coffeeOrderRepository.save(order1);
        log.info("Order:{}", order1);
        coffeeOrderRepository.save(order2);
        log.info("Order:{}", order2);
    }
}
